#ifndef DEFINES_H
#define DEFINES_H

#include <string>
#include <list>
#include <map>

#include "libraries\pdc34dllw\include\curses.h"

#include "typedefs.h"

const unsigned int MAP_X = 80;
const unsigned int MAP_Y = 20;

const int DIR_N = 1;
const int DIR_E = 2;
const int DIR_W = 4;
const int DIR_S = 8;
const int DIR_NE = DIR_N | DIR_E;
const int DIR_SE = DIR_S | DIR_E;
const int DIR_NW = DIR_N | DIR_W;
const int DIR_SW = DIR_S | DIR_W;

const unsigned int KEY_NUM1 = 455;
const unsigned int KEY_NUM2 = 456;
const unsigned int KEY_NUM3 = 457;
const unsigned int KEY_NUM4 = 452;
const unsigned int KEY_NUM5 = 453;
const unsigned int KEY_NUM6 = 454;
const unsigned int KEY_NUM7 = 449;
const unsigned int KEY_NUM8 = 450;
const unsigned int KEY_NUM9 = 451;
const unsigned int KEY_NUM0 = 506;
const unsigned int KEY_NUMM = 464;
const unsigned int KEY_NUMP = 465;

const unsigned int A_KEY = 97;
const unsigned int C_KEY = 99;
const unsigned int D_KEY = 100;
const unsigned int F_KEY = 102;
const unsigned int G_KEY = 103;
const unsigned int H_KEY = 104;
const unsigned int I_KEY = 105;
const unsigned int K_KEY = 107;
const unsigned int M_KEY = 109;
const unsigned int O_KEY = 111;
const unsigned int P_KEY = 112;
const unsigned int S_KEY = 115;
const unsigned int T_KEY = 116;
const unsigned int W_KEY = 119;
const unsigned int COMMA_KEY = 44;
const unsigned int DOT_KEY = 46;
const unsigned int QUESTION_KEY = 63;
const unsigned int KEY_STAR = 463;
const unsigned int KEY_SLASH = 458;
const unsigned int KEY_PLUS = 43;
const unsigned int KEY_MINUS = 45;
const unsigned int KEY_STDOWN = 62;

const unsigned int CTRL_D = 4;

const unsigned int ESC_KEY = 27;
const unsigned int EXIT_KEY = 17;
const unsigned int ENTER_KEY = 10;

// Colors

#define COLOR_OGREEN COLOR_PAIR( 1 )
#define COLOR_GREENB COLOR_OGREEN | A_BOLD
#define COLOR_ORED COLOR_PAIR( 2 )
#define COLOR_REDB COLOR_ORED | A_BOLD
#define COLOR_OBLUE COLOR_PAIR( 3 )
#define COLOR_BLUEB COLOR_OBLUE | A_BOLD
#define COLOR_OWHITE COLOR_PAIR( 4 )
#define COLOR_WHITEB COLOR_OWHITE | A_BOLD
#define COLOR_GRAY COLOR_OWHITE | A_DIM
#define COLOR_OCYAN COLOR_PAIR( 5 )
#define COLOR_CYANB COLOR_OCYAN | A_BOLD
#define COLOR_OYELLOW COLOR_PAIR( 6 )
#define COLOR_YELLWB COLOR_OYELLOW | A_BOLD
#define COLOR_OMAGENTA COLOR_PAIR( 7 )
#define COLOR_MAGENTAB COLOR_OMAGENTA | A_BOLD

#define COLOR_BLOOD COLOR_PAIR( 8 ) | A_BOLD

// Type casts

Armor * isArmor( MapObject * );
Weapon * isWeapon( MapObject * );
Item * isItem( MapObject * );
Consumable * isConsumable( MapObject * );
Monster * isMonster( MapObject * );

// helpers

Monster * spawnMonster( monster_t, int x, int y );
Armor * spawnArmor( armor_t, int x, int y );
Weapon * spawnWeapon( weapon_t, int x, int y );
Consumable * spawnConsumable( consumable_t, int x, int y );

Monster * spawnMonster( monster_t, MapObject * );
Armor * spawnArmor( armor_t, MapObject * );
Weapon * spawnWeapon( weapon_t, MapObject * );
Consumable * spawnConsumable( consumable_t, MapObject * );

template< typename T >
T * instance()
{
	return new T();
}

#define DECLARE_INSTANCE template< typename T > friend T * instance< T >();
//#define DECLARE_WEAPON_BASE_CONSTRUCT

Tile * tileAt( int x, int y );
Tile * mapTileAt( map *, int x, int y );
extern inline Tile * tileAt( const MapObject * );
extern inline Tile * mapTileAt( map *, const MapObject * );
int getDistance( const Tile * start, const Tile * end );
extern inline int getDistance( const MapObject * start, const MapObject * end );
int getDir( int x0, int y0, int x1, int y1 );
extern inline int getDir( const MapObject * start, const MapObject * end );
Monster * getLiveMonster( const Tile * );
extern inline Monster * getLiveMonster( int x, int y );
Monster * getLiveMonster( const MapObject *, int direction );
std::list< Tile * > getTilesRad( const MapObject * center, int radius );

// Functions' prototypes

void initRand();
int mrand();
int mrand( int );
void drawLine( int x0, int x1, int y0, int y1 );
void fillScreen( char = ' ', int y0 = -1, int x0 = -1, int rows = -1, int columns = -1 );
void fillWScreen( WINDOW *, char = ' ', int y0 = -1, int x0 = -1, int rows = -1, int columns = -1 );
WINDOW * newScreen( int height = 25, int width = 80, int y0 = 0, int x0 = 0 );
void deleteScreen( WINDOW * );
int getXAdj( int direction );
int getYAdj( int direction );
void getAdj( int direction, int & x, int & y );
int getKeyDir( int key );
bool prob( int );
std::string numToString( int );
void delay( int ms );
bool isMovKey( int );

int d20();

#endif